package com.tianji.promotion.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.promotion.constants.RedisConstant;
import com.tianji.promotion.domain.po.Coupon;
import com.tianji.promotion.domain.po.ExchangeCode;
import com.tianji.promotion.domain.query.CodeQuery;
import com.tianji.promotion.domain.vo.CouponPageVO;
import com.tianji.promotion.enums.ExchangeCodeStatus;
import com.tianji.promotion.mapper.ExchangeCodeMapper;
import com.tianji.promotion.service.IExchangeCodeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.promotion.utils.CodeUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 兑换码 服务实现类
 * </p>
 *
 * @author rui
 * @since 2024-08-05
 */
@Service
@RequiredArgsConstructor
public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, ExchangeCode> implements IExchangeCodeService {
    private final StringRedisTemplate redisTemplate;
    @Override
    @Async("generateExchangeCodeExecutor")
    public void generateExchangeCode(Coupon coupon) {
        //1.在redis里面用incrby缓存兑换码的唯一自增id
        //1.1判断空
        if(coupon == null){
            return;
        }
        //1.2 redis缓存更新自增的值
        String key = RedisConstant.COUPON_CODE_SERIAL;
        Long total = redisTemplate.opsForValue().increment(key, coupon.getTotalNum());
        //2.生成兑换码
        //2.1 生成的兑换码 由增长之前的值到total，比如原来的redis值为5000，
        // 此次由5001到增加的发放优惠券数量（2000）即7000，则5001 = total - 发放优惠券数量
        if(total == null){
            return;
        }
        int begin = total.intValue() - coupon.getTotalNum() + 1;
        List<ExchangeCode> list = new ArrayList<>();
        for (int i = begin;i<=total.intValue();i++){
            String code = CodeUtil.generateCode(i, coupon.getId());
            ExchangeCode exchangeCode = new ExchangeCode();
            exchangeCode.setCode(code);
            exchangeCode.setId(i);
            exchangeCode.setExchangeTargetId(coupon.getId());
            exchangeCode.setStatus(ExchangeCodeStatus.UNUSED);
            exchangeCode.setExpiredTime(coupon.getIssueEndTime());
            list.add(exchangeCode);
        }
        //3.批量存入数据库
        saveBatch(list);

        // 4.写入Redis缓存，member：couponId，score：兑换码的最大序列号
        redisTemplate.opsForZSet().add(RedisConstant.COUPON_CODE_RANGE, coupon.getId().toString(), total);
    }

    @Override
    public PageDTO<CouponPageVO> pageQueryCodeByStatus(CodeQuery query) {
        //1.根据状态分页查找兑换码
        Page<ExchangeCode> page = lambdaQuery()
                .eq(ExchangeCode::getExchangeTargetId, query.getCouponId())
                .eq(ExchangeCode::getStatus, query.getStatus())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<ExchangeCode> records = page.getRecords();
        if(CollUtil.isEmpty(records)){
            return PageDTO.empty(0L,0L);
        }
        //2.封装返回数据
        List<CouponPageVO> voList = new ArrayList<>(records.size());
        for (ExchangeCode record : records) {
            CouponPageVO vo = new CouponPageVO();
            if(record!=null){
                vo.setId(Long.valueOf(record.getId()));
                vo.setName(record.getCode());
            }
            voList.add(vo);
        }
        return PageDTO.of(page,voList);
    }
}
